package com.atguigu.ssyx.product.service.impl;

import com.atguigu.ssyx.common.constant.RedisConst;
import com.atguigu.ssyx.common.exception.SsyxException;
import com.atguigu.ssyx.common.result.ResultCodeEnum;
import com.atguigu.ssyx.model.product.SkuAttrValue;
import com.atguigu.ssyx.model.product.SkuImage;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.model.product.SkuPoster;
import com.atguigu.ssyx.mq.constant.MqConst;
import com.atguigu.ssyx.mq.service.RabbirService;
import com.atguigu.ssyx.product.mapper.SkuInfoMapper;
import com.atguigu.ssyx.product.service.ISkuAttrValueService;
import com.atguigu.ssyx.product.service.ISkuImageService;
import com.atguigu.ssyx.product.service.ISkuInfoService;
import com.atguigu.ssyx.product.service.ISkuPosterService;
import com.atguigu.ssyx.vo.product.SkuInfoQueryVo;
import com.atguigu.ssyx.vo.product.SkuInfoVo;
import com.atguigu.ssyx.vo.product.SkuStockLockVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * sku信息 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-06-23
 */
@Service
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfo> implements ISkuInfoService {

    //图片
    @Autowired
    private ISkuImageService imageService;

    //属性
    @Autowired
    private ISkuAttrValueService attrValueService;


    //海报
    @Autowired
    private ISkuPosterService posterService;


    @Autowired
    private RabbirService rabbitService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public IPage<SkuInfo> selectPage(Page<SkuInfo> pageParam, SkuInfoQueryVo skuInfoQueryVo) {

        LambdaQueryWrapper<SkuInfo> wrapper = new LambdaQueryWrapper<>();

//        筛选关键字   商品分类  商品类型
        //获取条件值
        String keyword = skuInfoQueryVo.getKeyword();
        String skuType = skuInfoQueryVo.getSkuType();
        Long categoryId = skuInfoQueryVo.getCategoryId();
        System.out.println(categoryId);
        System.out.println(keyword + "" + skuType + "" + categoryId);
        if (!StringUtils.isEmpty(keyword)) {
            wrapper.like(SkuInfo::getSkuName, keyword);
        }
        if (!StringUtils.isEmpty(skuType)) {
            wrapper.eq(SkuInfo::getSkuType, skuType);
        }
        if (categoryId != null) {
            wrapper.eq(SkuInfo::getCategoryId, categoryId);
        }

        IPage page = baseMapper.selectPage(pageParam, wrapper);
        return page;
    }

    /**
     * 添加商品sku商品
     *
     * @param skuInfoVo
     */
    @Override
    public void saveSkuInfo(SkuInfoVo skuInfoVo) {
        SkuInfo skuInfo = new SkuInfo();
//        属性名字一样就可以复制过去.
        BeanUtils.copyProperties(skuInfoVo, skuInfo);
        int insert = baseMapper.insert(skuInfo);
//        1.添加基本信息,

//        2.取出各个其他信息.

        List<SkuPoster> skuPosterList = skuInfoVo.getSkuPosterList();
        if (!CollectionUtils.isEmpty(skuPosterList)) {
            for (SkuPoster skuPoster : skuPosterList) {
                skuPoster.setSkuId(skuInfo.getId());
            }
            posterService.saveBatch(skuPosterList);
        }


        List<SkuImage> skuImagesList = skuInfoVo.getSkuImagesList();

        if (!CollectionUtils.isEmpty(skuImagesList)) {
            for (SkuImage skuImage : skuImagesList) {
                skuImage.setSkuId(skuInfo.getId());
            }
            imageService.saveBatch(skuImagesList);
        }


        List<SkuAttrValue> skuAttrValueList = skuInfoVo.getSkuAttrValueList();


//      3.保存到其他表中
        if (!CollectionUtils.isEmpty(skuAttrValueList)) {
            for (SkuAttrValue skuAttrValue : skuAttrValueList) {
                skuAttrValue.setSkuId(skuInfo.getId());
            }
        }
        attrValueService.saveBatch(skuAttrValueList);
    }


    /**
     * 返回商品基本信息
     *
     * @param id
     * @return
     */
    @Override
    public SkuInfo getSkuInfo(Long id) {
        SkuInfoVo skuInfoVo = new SkuInfoVo();

        SkuInfo skuInfo = baseMapper.selectById(id);
        BeanUtils.copyProperties(skuInfo, skuInfoVo);
//        获得照片集合

        LambdaQueryWrapper<SkuImage> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(SkuImage::getSkuId, id);
        List<SkuImage> list = imageService.list(lambdaQueryWrapper);
        skuInfoVo.setSkuImagesList(list);

//      获得海报图片集合.
        LambdaQueryWrapper<SkuPoster> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper1.eq(SkuPoster::getSkuId, id);
        List<SkuPoster> list1 = posterService.list(lambdaQueryWrapper1);
        skuInfoVo.setSkuPosterList(list1);

//      获得属性
        LambdaQueryWrapper<SkuAttrValue> skuAttrValueLambdaQueryWrapper = new LambdaQueryWrapper<>();
        skuAttrValueLambdaQueryWrapper.eq(SkuAttrValue::getSkuId, id);
        List<SkuAttrValue> list2 = attrValueService.list(skuAttrValueLambdaQueryWrapper);
        skuInfoVo.setSkuAttrValueList(list2);

        return skuInfoVo;
    }

    @Override
    public void updateSkuInfo(SkuInfoVo skuInfoVo) {
        SkuInfo skuInfo = new SkuInfo();
        BeanUtils.copyProperties(skuInfoVo, skuInfo);
        int i = baseMapper.updateById(skuInfo);


        Long id = skuInfoVo.getId();


//        海报图片删除增加/
        posterService.remove(new LambdaQueryWrapper<SkuPoster>().eq(SkuPoster::getSkuId, id));
        List<SkuPoster> skuPosterList = skuInfoVo.getSkuPosterList();
        if (!CollectionUtils.isEmpty(skuPosterList)) {
            for (SkuPoster skuPoster : skuPosterList) {
                skuPoster.setSkuId(skuInfo.getId());
            }
            posterService.saveBatch(skuPosterList);
        }


//删除sku图片
        imageService.remove(new LambdaQueryWrapper<SkuImage>().eq(SkuImage::getSkuId, id));
        //保存sku图片
        List<SkuImage> skuImagesList = skuInfoVo.getSkuImagesList();
        if (!CollectionUtils.isEmpty(skuImagesList)) {

            int sort = 1;
            for (SkuImage skuImages : skuImagesList) {
                skuImages.setSkuId(id);
                skuImages.setSort(sort);
                sort++;
            }

            imageService.saveBatch(skuImagesList);
        }


        attrValueService.remove(new LambdaQueryWrapper<SkuAttrValue>().eq(SkuAttrValue::getSkuId, id));
        //保存sku平台属性
        List<SkuAttrValue> skuAttrValueList = skuInfoVo.getSkuAttrValueList();
        if (!CollectionUtils.isEmpty(skuAttrValueList)) {
            int sort = 1;
            for (SkuAttrValue skuAttrValue : skuAttrValueList) {
                skuAttrValue.setSkuId(id);
                skuAttrValue.setSort(sort);
                sort++;
            }
            attrValueService.saveBatch(skuAttrValueList);
        }
    }

    /**
     * 上下架
     *
     * @param skuId
     * @param status
     */
    @Override
    public void publish(Long skuId, Integer status) {
        // 更改发布状态
        if (status == 1) {
            SkuInfo skuInfoUp = new SkuInfo();
            skuInfoUp.setId(skuId);
            skuInfoUp.setPublishStatus(1);
            baseMapper.updateById(skuInfoUp);
            //TODO 商品上架 后续会完善：发送mq消息更新es数据
            rabbitService.sendMessage(MqConst.EXCHANGE_GOODS_DIRECT, MqConst.ROUTING_GOODS_UPPER, skuId);

        } else {
            SkuInfo skuInfoUp = new SkuInfo();
            skuInfoUp.setId(skuId);
            skuInfoUp.setPublishStatus(0);
            baseMapper.updateById(skuInfoUp);
            //TODO 商品下架 后续会完善：发送mq消息更新es数据
            rabbitService.sendMessage(MqConst.EXCHANGE_GOODS_DIRECT, MqConst.ROUTING_GOODS_LOWER, skuId);
        }
    }

    @Override
    public void check(Long skuid, Integer status) {
        SkuInfo skuInfo = baseMapper.selectById(skuid);
        skuInfo.setCheckStatus(status);
        baseMapper.updateById(skuInfo);
    }

    @Override
    public void isNewPerson(Long skuId, Integer status) {
        SkuInfo skuInfoUp = new SkuInfo();
        skuInfoUp.setId(skuId);
        skuInfoUp.setIsNewPerson(status);
        baseMapper.updateById(skuInfoUp);
    }

    @Override
    public List<SkuInfo> findsSkuInfoList(List<Long> skuIdList) {
        List<SkuInfo> skuInfos = baseMapper.selectBatchIds(skuIdList);
        return skuInfos;
    }

    @Override
    public List<SkuInfo> findSkuInfoByKeyword(String keyword) {
        LambdaQueryWrapper<SkuInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(SkuInfo::getSkuName, keyword);
        List<SkuInfo> list = baseMapper.selectList(wrapper);
        return list;
    }

    //    获得新人专项商品。
    @Override
    public List<SkuInfo> findNewPersonSkuInfoList() {
//        1.商品是否是新人专享
//        2.是否上架，是上架或者是下架的话会操作es
//         3.显示上架

        Page<SkuInfo> page = new Page<>(1, 1);

        LambdaQueryWrapper<SkuInfo> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(SkuInfo::getIsNewPerson, 1).eq(SkuInfo::getPublishStatus, 1).orderByDesc(SkuInfo::getStock);//库存
        Page<SkuInfo> skuInfoPage = baseMapper.selectPage(page, wrapper);
        List<SkuInfo> records = skuInfoPage.getRecords();
        return records;
    }

    /**
     * 返回商品全部信息.
     *
     * @param id
     * @return
     */
    @Override
    public SkuInfoVo getSkuInfoVo(Long skuId) {
        SkuInfoVo skuInfoVo = new SkuInfoVo();
//       1. 根据id查询出来skuInfo
        SkuInfo skuInfo = baseMapper.selectById(skuId);

//        2.查询属性
        List<SkuAttrValue> skuattrValueList = attrValueService.getAttrValueListBySkuId(skuId);

//        3.查询海报。
        List<SkuPoster> skuPosterList = posterService.findBySkuPosterId(skuId);

//        4.获得商品图片。
        List<SkuImage> skuImageList = imageService.findSkuImageList(skuId);

        BeanUtils.copyProperties(skuInfo, skuInfoVo);
        skuInfoVo.setSkuAttrValueList(skuattrValueList);
        skuInfoVo.setSkuPosterList(skuPosterList);
        skuInfoVo.setSkuImagesList(skuImageList);
        return skuInfoVo;
    }

    /**
     * 就是成功全部锁定的话,把数据放到redis.
     * 锁定失败的话，全部 解锁 库存。
     *
     * @param skuStockLockVoList
     * @param orderNo
     * @return
     */
    @Override
    public Boolean checkAndLock(List<SkuStockLockVo> skuStockLockVoList, String orderNo) {
//        商品不为空
        if (CollectionUtils.isEmpty(skuStockLockVoList)) {
            throw new SsyxException(ResultCodeEnum.DATA_ERROR);
        }
//验证库存，并且锁定库存
//
        skuStockLockVoList.stream().forEach(skuStockLockVo -> {
            this.checkLock(skuStockLockVo);
        });
//只要有一个商品锁定失败，就解锁所有商品。
        boolean b = skuStockLockVoList.stream().anyMatch(skuStockLockVo -> !skuStockLockVo.getIsLock());
        if (b) {
//            所有锁定成功的商品都解锁。
//               只要有一个商品锁定失败，就全部解锁。
            skuStockLockVoList.stream().filter(SkuStockLockVo::getIsLock).forEach(SkuStockLockVo -> {
                baseMapper.unlockStock(SkuStockLockVo.getSkuId(), SkuStockLockVo.getSkuNum());
            });

            return false;
        } else {
            // 如果所有商品都锁定成功的情况下，需要缓存锁定信息到redis。以方便将来解锁库存 或者 减库存
            // 以orderToken作为key，以lockVos锁定信息作为value
            this.redisTemplate.opsForValue().set(RedisConst.SROCK_INFO + orderNo, skuStockLockVoList);
            return true;
        }

    }

    @Autowired
    private RedissonClient redissonClient;


    @Autowired
    private SkuInfoMapper skuInfoMapper;


    /**
     * 判断每个商品的库存是否充足，并且锁定库存.
     *
     * @param skuStockLockVo
     */
    private void checkLock(SkuStockLockVo skuStockLockVo) {
//        获得公平锁.
        RLock fairLock = this.redissonClient.getFairLock(RedisConst.SKUKEY_PREFIX + skuStockLockVo.getSkuId());
//        加锁
        fairLock.lock();


//   这是一个


        try {
//        验证库存
            SkuInfo skuInfo = baseMapper.checkStock(skuStockLockVo.getSkuId(), skuStockLockVo.getSkuNum());
            if (skuInfo == null) {
//                库存不足，锁定失败。




                skuStockLockVo.setIsLock(false);
                return;
            }
//                锁定成功，更新库存。

            Integer rows = baseMapper.lockStock(skuStockLockVo.getSkuId(), skuStockLockVo.getSkuNum());
             if (rows == 1) {
                skuStockLockVo.setIsLock(true);
            }

//        锁定库存


//        更新库存.

        } finally {
//            验证库存.
            fairLock.unlock();
        }
    }
}
